package com.tianluo.tianluobookstore.service.impl;

import com.tianluo.tianluobookstore.BookPO;
import com.tianluo.tianluobookstore.OrderPO;
import com.tianluo.tianluobookstore.enums.BookCodeEnum;
import com.tianluo.tianluobookstore.enums.OrderCodeEnum;
import com.tianluo.tianluobookstore.enums.OrderStatus;
import com.tianluo.tianluobookstore.enums.PaymentStatus;
import com.tianluo.tianluobookstore.exception.BizException;
import com.tianluo.tianluobookstore.repository.BookRepository;
import com.tianluo.tianluobookstore.repository.OrderRepository;
import com.tianluo.tianluobookstore.request.CreateOrderRequest;
import com.tianluo.tianluobookstore.service.BookService;
import com.tianluo.tianluobookstore.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import org.yaml.snakeyaml.constructor.DuplicateKeyException;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private BookRepository bookRepository;

    @Override
    public OrderPO queryOrderByBizSeq(String bizSeq) {
        return orderRepository.queryOrderByBizSeq(bizSeq);
    }

    @Override
    public String createOrder(CreateOrderRequest request) {

        return transactionTemplate.execute(status -> {
            try {
                // 执行数据库操作
                OrderPO orderPO = buildOrder(request);
                if(hitIdempotentAfterSaveOrder(orderPO, request)){
                    return orderPO.getOrderId();
                }

                BookPO bookPO = bookRepository.queryBookById(request.getBookId());
                if (Objects.isNull(bookPO)) {
                    throw new BizException(BookCodeEnum.BOOK_NOT_FOUND.getCode(), BookCodeEnum.BOOK_NOT_FOUND.getMessage());
                }
                Integer oldVersion = bookPO.getVersion();
                Integer num = bookPO.getStockQuantity();

                if (num <= 0) {
                    throw new BizException(BookCodeEnum.BOOK_NUM_NOT_ENOUGH.getCode(), BookCodeEnum.BOOK_NUM_NOT_ENOUGH.getMessage());
                }

                //扣减库存
                Integer stockQuantity = num - 1;
                //乐观锁更新书籍库存数量
                int result = bookRepository.updateBookStockByIdAndVersion(bookPO.getId(), stockQuantity, oldVersion);
                if (result > 0) {
                    return orderPO.getOrderId();
                }
                //乐观锁更新失败，需要回滚事务
                throw new BizException(OrderCodeEnum.CREATE_ORDER_FAIL.getCode(), OrderCodeEnum.CREATE_ORDER_FAIL.getMessage());
            } catch (Exception ex) {
                // 如果发生异常，则回滚事务
                status.setRollbackOnly();
                throw ex; // 可以选择重新抛出异常或进行其他处理
            }
        });
    }

    @Override
    public OrderPO queryOrderByOrderId(String orderId) {
        return orderRepository.queryOrderByOrderId(orderId);
    }

    @Override
    public int cancelOrder(String orderId) {
        return orderRepository.cancelOrder(orderId);
    }

    @Override
    public boolean processTimeoutOrders(Date timeoutTime, Integer currentPage, Integer pageSize) {
        Integer offset = (currentPage - 1) * pageSize;
        List<OrderPO> orderPOList = orderRepository.processTimeoutOrders(timeoutTime, currentPage, offset);
        //等于表示还有下一页
        return pageSize == orderPOList.size();
    }

    @Override
    public boolean isOrderPaid(String orderId) {
        OrderPO orderPO = queryOrderByOrderId(orderId);
        if (Objects.nonNull(orderPO) && orderPO.getPaymentStatus().equals(PaymentStatus.PAID.getCode())) {
            return Boolean.TRUE;
        }
        return false;
    }

    @Override
    public int updateOrderStatus(String orderId, String status, String preStatus,String paymentStatus,String prePaymentStatus) {
        return orderRepository.updateOrderStatus(orderId, status,preStatus, paymentStatus,prePaymentStatus);
    }

    private boolean hitIdempotentAfterSaveOrder(OrderPO orderPO, CreateOrderRequest request) {
        try {
            orderRepository.createOrder(orderPO);
        } catch (DuplicateKeyException e) {
            orderPO = orderRepository.queryOrderByBizSeq(request.getBizSeq());
            if (Objects.isNull(orderPO)) {
                throw new BizException(OrderCodeEnum.ORDER_NOT_FOUND.getCode(), OrderCodeEnum.ORDER_NOT_FOUND.getMessage());
            }
            log.info("命中幂等，bizSeq：{}", request.getBizSeq());
            //命中幂等~~
            return Boolean.TRUE;
        }

        //没有命中幂等
        return Boolean.FALSE;
    }

    private OrderPO buildOrder(CreateOrderRequest request) {
        OrderPO orderPO = new OrderPO();
        orderPO.setBookId(request.getBookId());
        orderPO.setOrderId(UUID.randomUUID().toString().replace("-", ""));
        orderPO.setUserId(request.getUserId());
        orderPO.setBizSeq(request.getBizSeq());
        orderPO.setPaymentStatus(PaymentStatus.NOT_PAID.getCode());
        orderPO.setStatus(OrderStatus.PENDING.getCode());
        orderPO.setCreatedTime(new Date());
        orderPO.setUpdatedTime(new Date());
        orderPO.setTotalAmount(request.getPrice().multiply(new BigDecimal(request.getQuantity())));
        orderPO.setVersion(1);
        orderPO.setCreator("田螺");
        orderPO.setModifier("田螺");
        return orderPO;
    }
}
